package ve.com.wayoyo.wuml_case.DibujoDiagramas;

import java.util.ArrayList;

import ve.com.wayoyo.wuml_case.Painter;
import ve.com.wayoyo.wuml_case.UserPref;
import ve.com.wayoyo.wuml_case.Exceptions.CardinalityException;
import ve.com.wayoyo.wuml_case.Exceptions.MultiplicityException;
import android.graphics.Canvas;
import android.graphics.Color;
import android.graphics.Paint;
import android.graphics.Path;
import android.graphics.Point;
import android.text.method.ArrowKeyMovementMethod;

public class CompAbstract extends Componente {

	private Paint _borderPaint = Painter.getInstancia().getDefaultBorderPaint();
	private Path _borderPath = new Path();

	private ArrayList<CompAtributo> _atributos = new ArrayList<CompAtributo>();
	private ArrayList<CompMetodo> _metodos = new ArrayList<CompMetodo>();
	private String longestString;


	public CompAbstract(String Titulo){
		if(UserPref.getInstancia().isUsingConvections() && Titulo.length() > 1){
			this.Titulo = Titulo.substring(0,1).toUpperCase() + Titulo.substring(1);
		}else{
			this.Titulo =  Titulo;
		}
		_centerPoint = new Point();
		Point punto = new Point();
		punto.x = 20;
		punto.y = 20;
		_height = 100;
		this.setAnchor(punto);
		_width = Painter.getInstancia().getTextPaint(false, 1).measureText(Titulo)+15;
		longestString = Titulo;
		if(_width < Painter.getInstancia().getTextPaint(true, 1).measureText("<<Abstract>>")+15){
			_width = Painter.getInstancia().getTextPaint(true, 1).measureText("<<Abstract>>")+15;
			longestString = "<<Abstract>>";
		}
		_topAnchors = new BorderAnchors(4, Anchor, new Point((int)(Anchor.x+_width),Anchor.y));
		_bottomAnchors = new BorderAnchors(4,new Point(Anchor.x,(int)(Anchor.y+_height)) , new Point((int)(Anchor.x+_width),(int)(Anchor.y+_height)));
		_leftAnchors = new BorderAnchors(4, Anchor , new Point((int)(Anchor.x),(int)(Anchor.y+_height)));
		_rightAnchors = new BorderAnchors(4,new Point((int)(Anchor.x+_width),(int)(Anchor.y)) , new Point((int)(Anchor.x+_width),(int)(Anchor.y+_height)));
	}

	@Override
	public void Dibujar(Canvas c,boolean isFcoused,float globalScale,int offSetX,int offSetY) {
		int posX = Anchor.x + offSetX;
		int posY = Anchor.y + offSetY;
		Paint _textPaint = Painter.getInstancia().getTextPaint(false, globalScale);
		Paint _cursivePaint = Painter.getInstancia().getTextPaint(true, globalScale);

		_width = _textPaint.measureText(longestString)/globalScale + 15;

		_borderPath.reset();
		_borderPath.moveTo(posX*globalScale, posY*globalScale);
		_borderPath.lineTo((posX+_width)*globalScale, posY*globalScale);
		_borderPath.lineTo((posX+_width)*globalScale, (posY+_height)*globalScale);
		_borderPath.lineTo(posX*globalScale, (posY+_height)*globalScale);
		_borderPath.close();
		c.drawPath(_borderPath,Painter.getInstancia().getBorderPaint(_currentState));

		/*//Dibujamos el Cuadro
		c.drawLine(posX*globalScale,posY*globalScale,(posX+_width)*globalScale,posY*globalScale,Painter.getInstancia().getBorderPaint(_currentState));
		c.drawLine(posX*globalScale,posY*globalScale,posX*globalScale,(posY+_height)*globalScale,Painter.getInstancia().getBorderPaint(_currentState));
		c.drawLine(posX*globalScale,(posY+_height)*globalScale,(posX+_width)*globalScale,(posY+_height)*globalScale,Painter.getInstancia().getBorderPaint(_currentState));
		c.drawLine((posX+_width)*globalScale,posY*globalScale,(posX+_width)*globalScale,(posY+_height)*globalScale,Painter.getInstancia().getBorderPaint(_currentState));
		 */

		//Dibujamos la linea del titulo
		c.drawLine(posX*globalScale,(posY+60)*globalScale,(posX+_width)*globalScale,(posY+60)*globalScale,_borderPaint);

		//Dibujamos el <<Interface>>
		float textSize = _textPaint.measureText("<<Abstract>>");
		float distToMid = (((_width)*globalScale) - textSize)/2;
		c.drawText("<<Abstract>>", (posX*globalScale)+distToMid, (posY+25)*globalScale, _cursivePaint);


		//Dibujamos el titulo
		textSize = _textPaint.measureText(Titulo);
		distToMid = (((_width)*globalScale) - textSize)/2;
		c.drawText(Titulo, (posX*globalScale)+distToMid ,(posY+55)*globalScale , _cursivePaint);

		_textPaint = Painter.getInstancia().getTextPaint(false, globalScale);

		//Dibujamos los atributos
		int puntoEscritura = 30;
		for (CompAtributo value : _atributos) {
			puntoEscritura += 30;
			if(value.isStatic()){
				_textPaint.setUnderlineText(true);
				c.drawText(value.getText(), (posX+5)*globalScale ,(posY+30+puntoEscritura)*globalScale , _textPaint);
				_textPaint.setUnderlineText(false);
			}else{
				c.drawText(value.getText(), (posX+5)*globalScale ,(posY+30+puntoEscritura)*globalScale , _textPaint);
			}
		}

		//Dibujamos la linea q separa metodos y atributos
		c.drawLine(posX*globalScale,(posY+45+puntoEscritura)*globalScale,(posX+_width)*globalScale,(posY+45+puntoEscritura)*globalScale,_borderPaint);
		puntoEscritura += 10;
		//Dibujamos los metodos
		for (CompMetodo value : _metodos) {
			if(value.isAbstract()){
				if(value.isStatic()){
					_cursivePaint.setUnderlineText(true);
					c.drawText(value.getText(), (posX+5)*globalScale ,(posY+60+puntoEscritura)*globalScale , _cursivePaint);
					_cursivePaint.setUnderlineText(false);
				}else{
					c.drawText(value.getText(), (posX+5)*globalScale ,(posY+60+puntoEscritura)*globalScale , _cursivePaint);
				}


			}else{
				if(value.isStatic()){
					_textPaint.setUnderlineText(true);
					c.drawText(value.getText(), (posX+5)*globalScale ,(posY+60+puntoEscritura)*globalScale , _textPaint);
					_textPaint.setUnderlineText(false);
				}else{
					c.drawText(value.getText(), (posX+5)*globalScale ,(posY+60+puntoEscritura)*globalScale , _textPaint);
				}
			}
			puntoEscritura += 30;

		}

		//Dibujamos Los conectores Padre
		for (CompConector value : _conectorsBegining) {
			value.Dibujar(c, isFcoused, globalScale, offSetX, offSetY);
		}

		_textPaint.setTextSize(25);
	}

	@Override
	public boolean CalcularVisibilidad(int offSetX, int offSetY,float GlobalScale) {
		boolean Visible = true;
		if((Anchor.x + _width) <= offSetX){
			Visible = false;
		}else if(Anchor.x <= offSetX + UserPref.getInstancia().getWinWidth()){
			Visible = false;
		}else if(Anchor.y > offSetY + UserPref.getInstancia().getWinHeight()){
			Visible = false;
		}else if((Anchor.y + _height) <= offSetY){
			Visible = false;
		}
		return Visible;
	}

	@Override
	public boolean calcularTouch(Point touch) {
		boolean respuesta = false;
		if((touch.x <= Anchor.x+_width) && (touch.x >= Anchor.x)){
			if((touch.y <= Anchor.y+_height) && (touch.y >= Anchor.y)){
				respuesta = true;
				//FactoryPopup.getPopup(VistaDiagrama.getVista(), "Clases");
			}
		}
		return respuesta;
	}

	public void addAtributo(CompAtributo nuevo){
		_atributos.add(nuevo);
		Paint textPaint = Painter.getInstancia().getTextPaint(false, 1);
		if(_width-10 < textPaint.measureText(nuevo.getText()) ){
			_width = textPaint.measureText(nuevo.getText())+10;
			longestString = nuevo.getText();
		}
		_height += 30;
		actualizarPuntoCentral();
		actualizarAchorsPoints();
	}

	@Override
	public void calculoLongitud(){
		Paint textPaint = Painter.getInstancia().getTextPaint(false, 1);
		_width = textPaint.measureText(Titulo)+15;
		_height = 100;
		if(_atributos.size() == 0){
			_height += 15;
		}else{
			for (CompAtributo atr : _atributos) {
				if(_width-10 < textPaint.measureText(atr.getText()) ){
					_width = textPaint.measureText(atr.getText())+10;
					longestString = atr.getText();
				}
				_height += 30;
			}
		}
		if(_metodos.size() == 0){
			_height += 15;
		}else{
			for (CompMetodo met : _metodos) {
				if(_width-10 < textPaint.measureText(met.getText()) ){
					_width = textPaint.measureText(met.getText())+10;
					longestString = met.getText();
				}
				_height += 30;
			}
		}
		actualizarAchorsPoints();
		actualizarPuntoCentral();
	}	

	public ArrayList<CompAtributo> get_atributos() {
		return _atributos;
	}

	public void set_atributos(ArrayList<CompAtributo> _atributos) {
		this._atributos = _atributos;
	}

	public void addMetodo(CompMetodo nuevo){
		_metodos.add(nuevo);
		Paint textPaint = Painter.getInstancia().getTextPaint(false, 1);
		if(_width-10 < textPaint.measureText(nuevo.getText()) ){
			_width = textPaint.measureText(nuevo.getText())+10;
			longestString = nuevo.getText();
		}
		_height += 30;
		actualizarPuntoCentral();
		actualizarAchorsPoints();
	}

	@Override
	public void setTitulo(String titulo) {
		Paint textPaint = Painter.getInstancia().getTextPaint(false, 1);
		if(UserPref.getInstancia().isUsingConvections()){
			this.Titulo = titulo.substring(0,1).toUpperCase() + titulo.substring(1);
			if(_width-10 < textPaint.measureText(Titulo) ){
				_width = textPaint.measureText(Titulo)+10;
				longestString = Titulo;

			}
		}else{
			this.Titulo =  titulo;
		}
		actualizarPuntoCentral();
	}

	@Override
	public CompConector calcularTouchConectores(Point touch) {
		for (CompConector value : _conectorsBegining) {
			if(value.calcularTouch(touch) == true)
				return value;
		}
		return null;
	}

	@Override
	public void actualizarPuntoCentral() {
		_centerPoint.set((Anchor.x+(int)(_width/2)), (Anchor.y+(int)(_height/2)));	
	}

	@Override
	public void actualizarAchorsPoints() {
		_topAnchors.actualizar(Anchor, new Point((int)(Anchor.x+_width),Anchor.y));
		_bottomAnchors.actualizar(new Point(Anchor.x,(int)(Anchor.y+_height)) , new Point((int)(Anchor.x+_width),(int)(Anchor.y+_height)));
		_leftAnchors.actualizar( Anchor , new Point((int)(Anchor.x),(int)(Anchor.y+_height)));
		_rightAnchors.actualizar(new Point((int)(Anchor.x+_width),(int)(Anchor.y)) , new Point((int)(Anchor.x+_width),(int)(Anchor.y+_height)));
	}

	public ArrayList<CompMetodo> get_metodos() {
		return _metodos;
	}

	public void set_metodos(ArrayList<CompMetodo> _metodos) {
		this._metodos = _metodos;
	}

	public CompMetodo getMetodoIndex(int index)
	{
		return this._metodos.get(index);
	}

	@Override
	public String generarDOM() {
		String DOM = "\t<Componente Tipo=\"Abstract\" Titulo=\""+Titulo+"\" ID=\""+ID+"\" AnchorX=\""+Anchor.x+"\" AnchorY=\""+Anchor.y+"\">\n";
		for (CompAtributo value : _atributos) {
			DOM = DOM + value.generarDOM();
		}
		for (CompMetodo value : _metodos) {
			DOM = DOM + value.generarDOM();
		}
		DOM = DOM + "\t</Componente>\n";
		return DOM;
	}

	@Override
	public String getConectorsDOM() {
		String DOM = "";
		for (CompConector value : _conectorsBegining) {
			DOM = DOM + value.gernerarDOM();
		}
		return DOM;
	}

	public String getCode(String Lenguaje) throws MultiplicityException{
		String code = "";
		Diagrama diagrama = VistaDiagrama.getVista().getDiagrama();
		if (diagrama instanceof DiagramaClases) {
			boolean needArrayList = false;
			ArrayList<CompAtributo> generatedComposition = new ArrayList<CompAtributo>();
			ArrayList<CompAtributo> generatedAggregation = new ArrayList<CompAtributo>();
			DiagramaClases diagramaClase = (DiagramaClases) diagrama;
			code = "package "+diagramaClase.getPackageName()+";\n\n";
			try{			
				for (CompConector value : _conectorsBegining) {
					if(value.get_fatherArrowType() == CompConector._arrowType.Composicion){
						String tituloCalse = diagramaClase.getComponenteById(value.get_childId()).getTitulo();
						CompAtributo nuevoAtributo = new CompAtributo("_"+tituloCalse, "private");
						nuevoAtributo.setTipoDato(tituloCalse);
						if(!value.get_fatherCardenalityRight().equals("1")){
							nuevoAtributo.setNombreVariable("_lista"+tituloCalse);
							nuevoAtributo.set_haveMultiplicity(true);
							nuevoAtributo.set_leftMultiplicity(value.get_fatherCardenalityLeft());
							nuevoAtributo.set_rightMultiplicity(value.get_fatherCardenalityRight());
						}
						generatedComposition.add(nuevoAtributo);
						needArrayList = true;
					}else if(value.get_fatherArrowType() == CompConector._arrowType.Agregacion){
						String tituloCalse = diagramaClase.getComponenteById(value.get_childId()).getTitulo();
						CompAtributo nuevoAtributo = new CompAtributo("_"+tituloCalse, "private");
						nuevoAtributo.setTipoDato(tituloCalse);
						if(!value.get_fatherCardenalityRight().equals("1")){
							nuevoAtributo.setNombreVariable("_lista"+tituloCalse);
							nuevoAtributo.set_haveMultiplicity(true);
							nuevoAtributo.set_leftMultiplicity(value.get_fatherCardenalityLeft());
							nuevoAtributo.set_rightMultiplicity(value.get_fatherCardenalityRight());
						}
						generatedAggregation.add(nuevoAtributo);
						needArrayList = true;
					}
				}
				for (CompConector value : _conectorsEnd) {
					if(value.get_childArrowType() == CompConector._arrowType.Composicion){
						String tituloCalse = diagramaClase.getComponenteById(value.get_fatherId()).getTitulo();
						CompAtributo nuevoAtributo = new CompAtributo("_"+tituloCalse, "private");
						nuevoAtributo.setTipoDato(tituloCalse);
						if(!value.get_childCardenalityRight().equals("1")){
							nuevoAtributo.setNombreVariable("_lista"+tituloCalse);
							nuevoAtributo.set_haveMultiplicity(true);
							nuevoAtributo.set_leftMultiplicity(value.get_childCardenalityLeft());
							nuevoAtributo.set_rightMultiplicity(value.get_childCardenalityRight());
						}
						generatedComposition.add(nuevoAtributo);
						needArrayList = true;
					}else if(value.get_childArrowType() == CompConector._arrowType.Agregacion){
						String tituloCalse = diagramaClase.getComponenteById(value.get_fatherId()).getTitulo();
						CompAtributo nuevoAtributo = new CompAtributo("_"+tituloCalse, "private");
						nuevoAtributo.setTipoDato(tituloCalse);
						if(!value.get_childCardenalityRight().equals("1")){
							nuevoAtributo.setNombreVariable("_lista"+tituloCalse);
							nuevoAtributo.set_haveMultiplicity(true);
							nuevoAtributo.set_leftMultiplicity(value.get_childCardenalityLeft());
							nuevoAtributo.set_rightMultiplicity(value.get_childCardenalityRight());
						}
						generatedAggregation.add(nuevoAtributo);
						needArrayList = true;
					}
				}

			}catch(CardinalityException e){

			}
			if(needArrayList == false){
				for (CompAtributo value : _atributos) {
					try{
						if(value.isMultiplicity() &&  value.get_rightMultiplicity().equals("*"))
							needArrayList = true;
					}catch (NullPointerException e) {

					}
				}
			}
			if(needArrayList){
				code = code + "\nimport java.util.ArrayList; \n\n";
			}
			code = code +"public abstract class " + Titulo;
			ArrayList<Componente> ListaImpements = new ArrayList<Componente>();
			Componente SuperClase = null;
			for (CompConector value : _conectorsBegining) {
				if(value.get_childArrowType() == CompConector._arrowType.Herencia){
					if(value.get_currentLineType() == CompConector.NORMAL_TYPE){
						SuperClase = diagramaClase.getComponenteById(value.get_childId());
					}else if(value.get_currentLineType() == CompConector.DASHED_TYPE){
						ListaImpements.add(diagramaClase.getComponenteById(value.get_childId()));
					}
				}
			}
			for (CompConector value : _conectorsEnd) {
				if(value.get_fatherArrowType()== CompConector._arrowType.Herencia){
					if(value.get_currentLineType() == CompConector.NORMAL_TYPE){
						SuperClase = diagramaClase.getComponenteById(value.get_fatherId());
					}else if(value.get_currentLineType() == CompConector.DASHED_TYPE){
						ListaImpements.add(diagramaClase.getComponenteById(value.get_fatherId()));
					}
				}
			}
			if(SuperClase != null){
				code = code + " extends "+SuperClase.getTitulo();
			}
			if(ListaImpements.size() > 0){
				code = code + " implements ";
				for (int i = 0; i < ListaImpements.size() -1; i++) {
					code = code + ListaImpements.get(i).getTitulo() +", ";
				}
				code = code + ListaImpements.get(ListaImpements.size() -1).getTitulo();
			}
			code = code + "{\n\n";

			for (CompAtributo value : _atributos) {
				code = code + "\t" + value.getCode(Lenguaje)+"\n";
			}
			for (CompAtributo value : generatedComposition) {
				code = code + "\t" + value.getCode(Lenguaje)+"\n";
			}
			for (CompAtributo value : generatedAggregation) {
				code = code + "\t" + value.getCode(Lenguaje)+"\n";
			}
			code = code + "\n";
			try{
				if(generatedComposition.size() > 0){
					code = code + "\n\t public "+Titulo+"(";
					for (int i = 0; i < generatedComposition.size() -1; i++) {
						if(generatedComposition.get(i).isMultiplicity()){
							if(generatedComposition.get(i).get_rightMultiplicity().equals("*")){
								code = code + "ArrayList<" + generatedComposition.get(i).getTipoDato() + "> lista"+generatedComposition.get(i).getTipoDato()+", ";
							}else{
								code = code + generatedComposition.get(i).getTipoDato()+"[] arreglo"+generatedComposition.get(i).getTipoDato()+", "; 
							}
						}else{
							code = code + generatedComposition.get(i).getTipoDato()+" "+generatedComposition.get(i).getTipoDato()+"Nuevo, "; 
						}
					}
					if(generatedComposition.get(generatedComposition.size() -1).isMultiplicity()){
						if(generatedComposition.get(generatedComposition.size() -1).get_rightMultiplicity().equals("*")){
							code = code + "ArrayList<" + generatedComposition.get(generatedComposition.size() -1).getTipoDato() + "> lista"+generatedComposition.get(generatedComposition.size() -1).getTipoDato();
						}else{
							code = code + generatedComposition.get(generatedComposition.size() -1).getTipoDato()+"[] arreglo"+generatedComposition.get(generatedComposition.size() -1).getTipoDato(); 
						}
					}else{
						code = code + generatedComposition.get(generatedComposition.size() -1).getNombreVariable() + " "+generatedComposition.get(generatedComposition.size() -1).getNombreVariable()+"Nuevo";
					}
					code = code + "){\n\t\t// TODO Codigo auto-generado por WUML \n";
					for (int i = 0; i < generatedComposition.size(); i++) {
						if((generatedComposition.get(i).isMultiplicity())){
							if(generatedComposition.get(i).get_rightMultiplicity().equals("*")){
								code = code + "\t\t"+"this."+generatedComposition.get(i).getNombreVariable()+" = "+"lista"+generatedComposition.get(i).getTipoDato()+";\n";
							}else{
								code = code + "\t\t"+"this."+generatedComposition.get(i).getNombreVariable()+" = "+"arreglo"+generatedComposition.get(i).getTipoDato()+";\n";
							}
						}else{
							code = code + "\t\t"+"this."+generatedComposition.get(i).getNombreVariable()+" = "+generatedComposition.get(i).getNombreVariable()+"Nuevo;\n";
						}
					}
					code = code + "\n\t }\n";		
				}
			}catch (Exception e) {
				System.out.println(e.getMessage());
			}

			for (CompMetodo value : _metodos) {
				code = code + "\t"+ value.getCode(Lenguaje, true)+"\n";
			}

			if(UserPref.getInstancia().isOverridingMethods()){
				for (Componente value : ListaImpements) {
					if (value instanceof CompInterface) {
						for (CompMetodo met : ((CompInterface) value).get_metodos()) {
							code = code + "\t"+met.getCode(Lenguaje, true);
						}

					}
				}
				if(SuperClase != null){
					if (SuperClase instanceof CompAbstract) {
						for (CompMetodo met :((CompAbstract) SuperClase).get_metodos()) {
							if(met.isAbstract()){
								code = code + "\t@Override\n";
								code = code + "\t"+met.getCode(Lenguaje, false);
							}
						}
					}
				}
			}


			code = code + "\n}";
		}
		return code;
	}

	public void eliminarAtributo(int position) {
		this.get_atributos().remove(position);
		calculoLongitud();
	}

	public void eliminarMetodo(int position) {
		this.get_atributos().remove(position);
		calculoLongitud();
	}

}
